package org.lh.ibernate.core.invoker;


import org.lh.ibernate.annotation.*;
import org.lh.ibernate.core.ISessionUtil;
import org.lh.ibernate.core.impl.SessionUtil;

import java.lang.reflect.*;

public class MethodProxy<T,PK> implements InvocationHandler {

    private ISessionUtil<T,PK> sessionUtil;
    private Class<T> beanClass;
    private Class<T> resultClazz;

    public ISessionUtil<T, PK> getSessionUtil(){
        return sessionUtil;
    }
    public void  setSessionUtil(SessionUtil<T,PK> sessionUtil){
        this.sessionUtil=sessionUtil;
    }


    /*
     *
     * @author idea
     * @date 2018/7/12
     * @param Class clazz
     * @return
     * @des 主要用于获取所关联的实体类bean
     */
    public MethodProxy(Class clazz) throws ClassNotFoundException {
        this.beanClass=clazz;
        Type[] type=beanClass.getGenericInterfaces();  //获取接口数组
        for (Type type1 : type) {
            if(type1.getTypeName().indexOf("IbernateBaseDao")>0){  //通过父类接口来获取相应的泛型类
                Type[] argType=((ParameterizedType) type1).getActualTypeArguments();
                 resultClazz= (Class<T>) Class.forName(argType[0].getTypeName());  //第一个参数是返回类型，第二个参数才是主键
            }
        }
    }


    /*
     *
     * @author idea
     * @date 2018/7/12
     * @param Object proxy, Method method, Object[] args
     * @return Object
     * @des 接入代理入口
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //如果传入进来的内容是一个已经实现的具体类，那么就可以直接跳过
        if(Object.class.equals(method.getDeclaringClass())){
            return method.invoke(proxy,args);
        }else{
            //如果传进来的是一个接口的话，就需要转换为代理对象来进行处理
            return run(method,args);
        }
    }

    /*
    *
    * @author idea
    * @date 2018/7/12
    * @param Method method,Object[] args
    * @return Object
    * @des 接口自动实例化产生函数的核心core
    */
    //TODO
    public Object run(Method method,Object[] args) throws Exception {
        this.setSessionUtil(new SessionUtil<T,PK>((Class<T>) resultClazz));
        AnnotationHandle<T,PK> annotationHandle=new AnnotationHandle<T,PK>();
        //先获取每个方法的dao函数注解里面的内容
        if(method.isAnnotationPresent(Query.class)){
            return annotationHandle.queryHandle(method,args,sessionUtil);

        }else if(method.isAnnotationPresent(Insert.class)){
            return annotationHandle.insertHandle(method,args,sessionUtil);

        }else if(method.isAnnotationPresent(Update.class)){
            return  annotationHandle.updateHandle(method,args,sessionUtil);

        } else if(method.isAnnotationPresent(Delete.class)){
            return  annotationHandle.deleteHandle(method,args,sessionUtil);

        } else if(method.isAnnotationPresent(BatchInsert.class)){
            return annotationHandle.batchInsertHandle(method,args,sessionUtil);

        } else if(method.isAnnotationPresent(FindOne.class)){
            T resultObj= (T) Class.forName(resultClazz.getName()).newInstance();
            return annotationHandle.findOne(method,args,sessionUtil,resultObj);

        } else if(method.isAnnotationPresent(FindAll.class)){
            T resultObj= (T) Class.forName(resultClazz.getName()).newInstance();
            return annotationHandle.findAll(method,args,sessionUtil,resultObj);

        } else if(method.isAnnotationPresent(QueryCallableStatement.class)){
            QueryCallableStatement qc=method.getAnnotation(QueryCallableStatement.class);
            String value=qc.value();
            return annotationHandle.callableStatementHandle(method,value,sessionUtil);
        }
        return null;
    }





}
